物件是 JavaScript 另一個大主題,光是 “almost everything in JavaScript is an object” 這句話就知道物件的重要。
物件是屬性名稱(key)和屬性值(value)的集合,我們很容易用 object literal 方式建立物件,並指派任何資料類型的值給屬性:
var obj = {
prop1: 1,
prop2: [],
prop3: {}
}
JavaScript 也讓我們能任意的更換、修改、刪除和新增屬性。
obj.prop1 = 1;
obj.prop1 = [];
delete obj.prop2;
obj.prop4 = "Hello";
經過修改後,我們的物件會變成
{
prop1: [],
prop3: {},
prop4: "Hello"
}
程式開發人員會避免重新造輪子,好用的程式碼最好能重複使用,而讓舊物件的功能可以沿用在新物件上面,就是利用原型(prototype)實作出來。
JavaScript 裡的每一個物件都能找到自己的原型,這個記錄是藏在物件的隱含屬性裡面。原型的作用是當物件在尋找某個屬性,而本身沒有這個屬性時,就把這個搜尋的工作委派到原型物件上。
打個比方,假設你和一群人參加一個猜謎遊戲,如果你知道問題,就能馬上回答,如果你不知道答案,可以問旁邊的人,他知道的話就告訴你。原型就是這樣而已。
// 建立三個物件,各自有自己的屬性
var kitty = { meow: true };
var doraemon = { purr: true };
var garfield = { hiss: true };
// kitty 只能存取自己的屬性 meow
console.log("meow" in kitty); // true
console.log("purr" in kitty); // false
console.log("hiss" in kitty); // false
// 將 doraemon 設為 kitty 的原型
Object.setPrototypeOf(kitty, doraemon);
// 現在 kitty 也會 purr 了
console.log("purr" in kitty); // true
// doraemon 不會 hiss
console.log("hiss" in doraemon); // false
// 將 garfield 設為 doraemon 的原型
Object.setPrototypeOf(doraemon, garfield);
// 現在 doraemon 也會 hiss 了
console.log("hiss" in doraemon); // true
// 透過 doraemon, kitty 也會 hiss
console.log("hiss" in kitty); // true
在範例裡,我們建立三個物件,各自有不同屬性,檢查屬性是否在物件裡,使用 in
。
將一個物件設為另一個物件的原型,使用物件方法Object.setPrototypeOf
。把doraemon
設為kitty
的原型後,就能在kitty
裡找不到purr
屬性時,到原型物件doraemon
裡去找,有找到就回傳其值。同樣過程發生在設garfield
為doraemon
的原型的時候。這時透過doraemon
,kitty
也能存取garfield
裡的hiss
屬性。
JavaScript 物件的原型對象是存在隱含屬性[[prototype]]
裡,使用Object.setPrototypeOf
可以修改它,需要代入二個參數,第一個參數是目前要更改原型的物件,第二個參數是目標物件。
像這樣透過原型將物件串連起來,就得到所謂的 “prototype chain”,在物件上搜尋屬性時,便是在這條鏈上移動。